using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace TripleMatch
{
    public class LevelManager : MonoBehaviour
    {
        private static LevelManager s;
        public static LevelManager S
        {
            get
            {
                return s;
            }
        }

        [SerializeField] LevelGenerator m_levelGenerator;

        private int m_continousWinCount;
        private int m_continousFailCount;
        private LevelGenerator.LevelGenerateData m_levelGenerateData = new LevelGenerator.LevelGenerateData();

        private void Awake()
        {
            s = this;
        }

        private void Start()
        {
            m_continousWinCount = 0;
            m_continousFailCount = 0;

            LevelGenerator.LevelGenerateData m_levelGenerateData = new LevelGenerator.LevelGenerateData();
            m_levelGenerateData.standardDifficulty = (StandardDifficulty)Mathf.Clamp(DataManager.S.difficulty - 1, 0, (int)StandardDifficulty.Hard);
            m_levelGenerateData.extraDifficulty = 0;

            //如果玩家是起始第一关，会直接进入关卡
            if (DataManager.S.level < 1)  StartGame();
        }

        #region Debug工具

        public StandardDifficulty standardDifficulty
        {
            get 
            {
                return m_levelGenerateData.standardDifficulty;
            }
        }

        public int extraDifficulty
        {
            get
            {
                return m_levelGenerateData.extraDifficulty;
            }
        }

        public void SwitchDifficultData()
        {
            DataManager.S.difficulty = (++DataManager.S.difficulty) % 3;
            m_levelGenerateData.standardDifficulty = (StandardDifficulty)Mathf.Clamp(DataManager.S.difficulty , 0, (int)StandardDifficulty.Hard);
        }

        public void SwitchExtraDifficultData()
        {
            m_levelGenerateData.extraDifficulty++;
        }

        #endregion

        #region 关卡控制

        public void StartGame()
        {
            //ShapeType shapeCurrentType = (ShapeType)Random.Range(0, (int)ShapeType.ShapeLast);
            //m_levelGenerateData.shapeType = shapeCurrentType;
            //m_levelGenerateData.gradientType = (GradientType)Random.Range(0, (int)GradientType.GradientLast);
            //m_levelGenerateData.offset = 0;

            ShapeType shapeCurrentType = ShapeType.Square;
            m_levelGenerateData.shapeType = shapeCurrentType;
            m_levelGenerateData.gradientType = GradientType.Increase;
            m_levelGenerateData.offset = 0;

            if (DataManager.S.level < 1)
            {
                m_levelGenerateData.standardDifficultyData = GameDefine.guideDifficultData;
            }
            else
            {
                if (m_continousWinCount == 2)
                {
                    m_levelGenerateData.extraDifficulty++;
                    m_continousWinCount = 0;

                    if (m_levelGenerateData.extraDifficulty > 10)
                    {
                        m_levelGenerateData.standardDifficulty = (StandardDifficulty)Mathf.Clamp((int)m_levelGenerateData.standardDifficulty + 1, 0, (int)StandardDifficulty.Hard);
                        m_levelGenerateData.extraDifficulty = 0;
                    }
                }

                if (m_continousFailCount == 1) { m_levelGenerateData.extraDifficulty--; }
                else if (m_continousFailCount > 1) { m_levelGenerateData.standardDifficulty = (StandardDifficulty)Mathf.Clamp((int)m_levelGenerateData.standardDifficulty - 1, 0, (int)StandardDifficulty.Hard); }
                else { }

                m_levelGenerateData.standardDifficultyData = GetDifficultData(m_levelGenerateData.standardDifficulty);
            }

            m_levelGenerator.Generate(m_levelGenerateData);
            UIManager.S.OpenGameUI();
        }

        public void DestroyGame()
        {
            m_levelGenerator.LevelDispose();
            UIManager.S.HideGameUI();
        }

        public void GameFail()
        {
            m_continousWinCount = 0;
            m_continousFailCount++;
            DataManager.S.level++;

            Debug.Log("GameFail");

            DecorationsManager.S.OnSettlement(out List<DecorationPiecesData> unSettleDatas, out List<int> decorations);
            UIManager.S.HideGameUI();
            UIManager.S.OpenGameFailUI(unSettleDatas, decorations, (isContinue) =>
            {
                if (isContinue)
                {
                    m_levelGenerator.LevelDispose();
                    StartGame();
                }
                else
                {
                    m_levelGenerator.LevelDispose();
                }
            });
        }

        public void GameWin()
        {
            m_continousFailCount = 0;
            m_continousWinCount++;
            DataManager.S.level++;

            Debug.Log("GameWin");

            DecorationsManager.S.OnSettlement(out List<DecorationPiecesData> unSettleDatas, out List<int> decorations);
            UIManager.S.HideGameUI();
            UIManager.S.OpenGameWinUI(unSettleDatas,decorations,(isContinue) =>
            {
                if (isContinue)
                {
                    m_levelGenerator.LevelDispose();
                    StartGame();
                }
                else
                {
                    m_levelGenerator.LevelDispose();
                }
            });
        }

        #endregion



        private LevelConfigData GetDifficultData(StandardDifficulty _standardDifficulty)
        {
            LevelConfigData difficultData;
            switch (_standardDifficulty)
            {
                case StandardDifficulty.Standard:
                    difficultData = GameDefine.standardDifficultData;
                    break;
                case StandardDifficulty.Hard:
                    difficultData = GameDefine.hardDifficultData;
                    break;
                case StandardDifficulty.Easy:
                default:
                    difficultData = GameDefine.easyDifficultData;
                    break;
            }
            return difficultData;
        }
    }
}
